package pub.guoxin.oops.collector.server;


import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.InetSocketAddress;

/**
 * Created by guoxin on 17-10-10.
 */
@Component
public class DataGatherServer {

    @Resource
    private DataGatherServerInitializer dataGatherServerInitializer;

    // UDP服务监听的数据通道
    private Channel channel;
    private final EventLoopGroup workerGroup = new NioEventLoopGroup();
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public ChannelFuture start(InetSocketAddress address) {
        Bootstrap bootstrap = new Bootstrap(); // udp不能使用ServerBootstrap
        bootstrap.group(workerGroup).channel(NioDatagramChannel.class); // 设置UDP通道
        bootstrap.handler(dataGatherServerInitializer); // 初始化处理器
        bootstrap.option(ChannelOption.SO_BROADCAST, true); // 支持广播
        // BACKLOG用于构造服务端套接字ServerSocket对象，标识当服务器请求处理线程全满时，用于临时存放已完成三次握手的请求的队列的最大长度。
        // 如果未设置或所设置的值小于1，Java将使用默认值50。
        bootstrap.option(ChannelOption.SO_BACKLOG, 128);
        bootstrap.option(ChannelOption.SO_RCVBUF, 1024 * 1024);// 设置UDP读缓冲区为1M
        bootstrap.option(ChannelOption.SO_SNDBUF, 1024 * 1024);// 设置UDP写缓冲区为1M

        logger.info("Data Gathering Server start success");
        logger.info("Address:" + address.getAddress() + "\tPort:" + address.getPort());
        // 绑定端口，开始接收进来的连接
        ChannelFuture future = bootstrap.bind(address).syncUninterruptibly();

        channel = future.channel();
        return future;
    }

    public void destroy() {
        if (channel != null) {
            channel.close();
        }
        workerGroup.shutdownGracefully();
    }

    public static void main(String[] args) {
        final DataGatherServer server = new DataGatherServer();
        InetSocketAddress address = new InetSocketAddress("127.0.0.1", 9090);

        ChannelFuture future = server.start(address);

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                server.destroy();
            }
        });
        // 等待服务器 socket 关闭 。
        // 这不会发生，可以优雅地关闭服务器。
        future.channel().closeFuture().awaitUninterruptibly();

    }
}